﻿using System;
using System.Windows;
using System.Diagnostics;
using System.Timers;
using System.Net;
using System.ServiceModel.Syndication;
using System.Windows.Controls;
using System.Windows.Threading;
using System.Windows.Media.Animation;
using RSSReader.Properties;
using System.ComponentModel;
using System.Windows.Data;
using System.Linq;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading.Tasks;

namespace RSSReader
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private FeedList feedList;

        private const string uriTextBoxDefaultText = "<Enter your RSS URL here>";
        private const string searchTextBoxDefaultText = "<Enter search text here>";

        CollectionViewSource feedItemsViewSource;

        TimeSpan updateInterval = new TimeSpan(0, 0, Settings.Default.UpdateIntervalInSeconds);
        DoubleAnimation updateProgressAnimation;
        GridLength sidePanelSize;
        public MainWindow()
        {
            InitializeComponent();
        }

        public MainWindow(FeedList feedList)
        {
            InitializeComponent();

            this.feedList = feedList;
            this.DataContext = feedList;

            this.tbNewUri.Text = uriTextBoxDefaultText;
            this.tbSearch.Text = searchTextBoxDefaultText;

            this.feedItemsViewSource = (CollectionViewSource)this.FindResource("ItemsViewSource");

            DispatcherTimer countDown = new DispatcherTimer();
            countDown.Tick += CountDown_Tick;
            countDown.Interval = updateInterval;

            this.pbUpdateFeeds.Minimum = 0.0;
            this.pbUpdateFeeds.Maximum = updateInterval.TotalSeconds;

            countDown.Start();

            //progress bar animation
            this.updateProgressAnimation = new System.Windows.Media.Animation.DoubleAnimation(0, updateInterval.TotalSeconds, new Duration(updateInterval));
            this.pbUpdateFeeds.BeginAnimation(ProgressBar.ValueProperty, updateProgressAnimation);
        }

        private async void CountDown_Tick(object sender, EventArgs e)
        {
            await this.feedList.UpdateAllFeedsAsync();

            //progress bar animation neu starten
            this.pbUpdateFeeds.BeginAnimation(ProgressBar.ValueProperty, updateProgressAnimation);
        }

        private async void btnRegister_Click(object sender, RoutedEventArgs e)
        {
            await this.RegisterChannelAsync();
        }

        private void btnUnregister_Click(object sender, RoutedEventArgs e)
        {
            this.Unregister((ObservableSyndicationFeed)lbFeeds.SelectedItem);
        }

        private void tbNewUri_GotFocus(object sender, RoutedEventArgs e)
        {
            if (tbNewUri.Text == uriTextBoxDefaultText)
            {
                this.tbNewUri.Text = string.Empty;
            }
        }

        private void tbNewUri_LostFocus(object sender, RoutedEventArgs e)
        {
            if (tbNewUri.Text == string.Empty)
            {
                this.tbNewUri.Text = uriTextBoxDefaultText;
            }
        }

        private void tbSearch_GotFocus(object sender, RoutedEventArgs e)
        {
            if (tbSearch.Text == searchTextBoxDefaultText)
            {
                this.tbSearch.Text = string.Empty;
            }
        }

        private void tbSearch_LostFocus(object sender, RoutedEventArgs e)
        {
            if (tbSearch.Text == string.Empty)
            {
                this.tbSearch.Text = searchTextBoxDefaultText;
            }
        }

        private void listBoxChannels_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            var feed = ((FrameworkElement)e.OriginalSource).DataContext as ObservableSyndicationFeed;
            if (feed != null)
            {
                feed.ShowBaseUriInBrowser();
            }
        }

        private void lbFeedItems_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            var item = ((FrameworkElement)e.OriginalSource).DataContext as ObservableSyndicationItem;
            if (item != null)
            {
                item.ShowItemInBrowser();
            }
        }

        private void RegisterChannel()
        {
            Uri newUri = new Uri(tbNewUri.Text, UriKind.Absolute);
            var feed = this.feedList.Register(newUri);
            lbFeeds.SelectedItem = feed;
            this.tbNewUri.Text = uriTextBoxDefaultText;
        }

        private async Task RegisterChannelAsync()
        {
            Uri newUri = new Uri(tbNewUri.Text, UriKind.Absolute);
            var feed = await this.feedList.RegisterAsync(newUri);
            lbFeeds.SelectedItem = feed;
            this.tbNewUri.Text = uriTextBoxDefaultText;
        }

        private async void tbNewUri_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
        {
            if (e.Key == System.Windows.Input.Key.Enter)
            {
                await this.RegisterChannelAsync();
                this.btnRegister.Focus();
            }
        }

        private void SidePanelButton_Click(object sender, RoutedEventArgs e)
        {
            if (SidePanelColumn.Width != new GridLength(0))
            {
                this.HideSidePanel();
            }
            else
            {
                this.ShowSidePanel();
            }
        }

        private void HideSidePanel()
        {
            this.SidePanelColumn.Width = new GridLength(this.SidePanelColumn.ActualWidth);
            this.sidePanelSize = SidePanelColumn.Width;

            var slideOutAnimation = new GridLengthAnimation();
            slideOutAnimation.From = SidePanelColumn.Width;
            slideOutAnimation.To = new GridLength(0);
            slideOutAnimation.EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseOut };
            slideOutAnimation.FillBehavior = FillBehavior.Stop;
            slideOutAnimation.Completed += SlideOutAnimation_Completed;
            this.SidePanelColumn.BeginAnimation(ColumnDefinition.WidthProperty, slideOutAnimation);
        }

        private void SlideOutAnimation_Completed(object sender, EventArgs e)
        {
            this.SidePanelColumn.Width = new GridLength(0);
        }

        private void ShowSidePanel()
        {
            var slideInAnimation = new GridLengthAnimation();
            slideInAnimation.From = new GridLength(0);
            slideInAnimation.To = this.sidePanelSize;
            slideInAnimation.EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseOut };
            slideInAnimation.FillBehavior = FillBehavior.Stop;
            slideInAnimation.Completed += SlideInAnimation_Completed;
            this.SidePanelColumn.BeginAnimation(ColumnDefinition.WidthProperty, slideInAnimation);
        }

        private void SlideInAnimation_Completed(object sender, EventArgs e)
        {
            this.SidePanelColumn.Width = this.sidePanelSize;
        }

        private void GridSplitter_LayoutUpdated(object sender, EventArgs e)
        {
            if (this.SidePanelColumn.ActualWidth == 0)
            {
                SidePanelButton.Content = ">";
            }
            else
            {
                SidePanelButton.Content = "<";
            }
        }

        private void ShowOnlyIfItemContainsText(object item, FilterEventArgs e)
        {
            var syndicationItem = (ObservableSyndicationItem)e.Item;

            if (cbShowOldItems.IsChecked == true)
            {
                CheckForSearchTextInItem(e, syndicationItem);
            }
            else 
            {
                if (syndicationItem.IsNew == true)
                {
                    CheckForSearchTextInItem(e, syndicationItem);
                }
                else
                {
                    e.Accepted = false;
                }
            }
        }

        private void CheckForSearchTextInItem(FilterEventArgs e, ObservableSyndicationItem syndicationItem)
        {
            if (tbSearch.Text == searchTextBoxDefaultText || tbSearch.Text == string.Empty)
            {
                e.Accepted = true;
            }
            else
            {
                if (syndicationItem.Summary.ToLowerInvariant().Contains(tbSearch.Text.ToLowerInvariant()) || syndicationItem.Title.ToLowerInvariant().Contains(tbSearch.Text.ToLowerInvariant()))
                {
                    e.Accepted = true;
                }
                else
                {
                    e.Accepted = false;
                }
            }
        }

        private void tbSearch_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (this.feedItemsViewSource != null && feedItemsViewSource.View != null)
                feedItemsViewSource.View.Refresh();
        }

        public void Unregister(ObservableSyndicationFeed feed)
        {
            this.feedList.Unregister(feed);
        }

        public void UpdateAllFeeds()
        {
            this.feedList.UpdateAllFeeds();
        }

        private void lbFeedItems_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            foreach (var item in e.RemovedItems)
            {
                ((ObservableSyndicationItem)item).MarkRead();
            }
        }

        private void cbShowOldItems_Checked(object sender, RoutedEventArgs e)
        {
            var itemsViewSource = (CollectionViewSource)this.FindResource("ItemsViewSource");

            if (itemsViewSource != null && itemsViewSource.View != null)
                itemsViewSource.View.Refresh();
        }

        private void cbShowOldItems_Unchecked(object sender, RoutedEventArgs e)
        {
            var itemsViewSource = (CollectionViewSource)this.FindResource("ItemsViewSource");

            if (itemsViewSource != null && itemsViewSource.View != null)
                itemsViewSource.View.Refresh();
        }

        private void MenuItem_Click_Copy_Link(object sender, RoutedEventArgs e)
        {
            var item = ((ObservableSyndicationFeed)lbFeeds.SelectedItem);
            string addresse = item.BaseUri.OriginalString;
            Clipboard.SetText(addresse);
        }

        private void MenuItem_Click_Delete_Feed(object sender, RoutedEventArgs e)
        {
            var item = ((ObservableSyndicationFeed)lbFeeds.SelectedItem);
            Unregister(item);
        }
    }
}